package com.binance.eureka.config;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.conn.HttpHostConnectException;
import org.springframework.core.env.Environment;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.binance.master.utils.HttpClientUtils;
import com.binance.master.utils.IPUtils;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.eureka.EurekaServerConfig;
import com.netflix.eureka.cluster.PeerEurekaNodes;
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
import com.netflix.eureka.resources.ServerCodecs;

import lombok.extern.log4j.Log4j2;

/**
 * Created by Fei.Huang on 2018/7/20.
 */
@Log4j2
public class BnbPeerEurekaNodes extends PeerEurekaNodes {
    
    private final String localNode;
    
    protected Environment env;
    
    public BnbPeerEurekaNodes(PeerAwareInstanceRegistry registry, EurekaServerConfig serverConfig,
            EurekaClientConfig clientConfig, ServerCodecs serverCodecs, ApplicationInfoManager applicationInfoManager,Environment env) {
        super(registry, serverConfig, clientConfig, serverCodecs, applicationInfoManager);
        this.env = env;
        this.localNode = IPUtils.getIp()+":"+this.env.getProperty("server.port");
    }

//    @Override
//    protected PeerEurekaNode createPeerEurekaNode(String peerEurekaNodeUrl) {
//        HttpReplicationClient replicationClient =
//                JerseyReplicationClient.createReplicationClient(serverConfig, serverCodecs, peerEurekaNodeUrl);
//        String targetHost = getNodeFromUrl(peerEurekaNodeUrl);
//        if (targetHost == null) {
//            targetHost = "host";
//        }
//        return new PeerEurekaNode(registry, targetHost, peerEurekaNodeUrl, replicationClient, serverConfig);
//    }

    @Override
    public boolean isInstanceURL(String url, InstanceInfo instance) {
        String hostName = getNodeFromUrl(url);
        String myInfoComparator = instance.getHostName()+":"+instance.getPort();
        if (clientConfig.getTransportConfig().applicationsResolverUseIp()) {
            myInfoComparator = instance.getIPAddr();
        }
        return hostName != null && hostName.equals(myInfoComparator);
    }

    public String getNodeFromUrl(String url) {
        String node = null;
        try {
            String newUrl = StringUtils.replace(url, "/eureka/", "/nodeInfo");
            String nodeInfoJsonStr = HttpClientUtils.postJson(newUrl, null);
            JSONObject nodeInfo = null;
            try {
                nodeInfo = JSON.parseObject(nodeInfoJsonStr); 
            } catch (Exception e) {
                log.warn("JSON parseObject Exception:{}", e.getMessage());
            }
            if(nodeInfo != null) {
                final String ip = nodeInfo.getString("ip");
                final String port = nodeInfo.getString("port");
                if (StringUtils.isAnyBlank(ip,port)) {
                    return this.localNode;
                }
                node = ip+":"+port;
            }else {
                return this.localNode;
            }
            log.info("original url:{}, node:{}", url, node);
        } catch (HttpHostConnectException e) {
            log.warn("HttpHostConnectException:{}", e.getMessage());
            return this.localNode;
        } catch (Exception e) {
            log.warn("hostFromUrl error:", e);
        }
        return node;
    }
}
